# services.py - 修复User类参数问题
import uuid
import hashlib
from datetime import datetime
from models import User, UserRole, Question, QuestionType, DifficultyLevel, Paper
import re
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from typing import List, Dict, Optional, Any


# services.py 中的 UserService 类修复
class UserService:
    def __init__(self, db):
        self.db = db

    def authenticate_user(self, username, password):
        """用户认证 - 增强兼容性"""
        try:
            user = self.db.get_user_by_username(username)
            if user:
                # 获取用户存储的密码
                stored_password = None
                if hasattr(user, 'password'):
                    stored_password = user.password
                elif hasattr(user, 'password_hash'):
                    stored_password = user.password_hash

                if stored_password:
                    # 先尝试直接比较（明文密码）
                    if password == stored_password:
                        print(f"✅ 用户认证成功（明文）: {username}")
                        return True, user

                    # 再尝试哈希比较
                    if self._hash_password(password) == stored_password:
                        print(f"✅ 用户认证成功（哈希）: {username}")
                        return True, user

                    print(f"❌ 密码错误: {username}")
                    print(f"🔍 输入密码哈希: {self._hash_password(password)}")
                    print(f"🔍 存储密码: {stored_password}")
                else:
                    print(f"❌ 用户密码字段为空: {username}")
                return False, None
            else:
                print(f"❌ 用户不存在: {username}")
                return False, None
        except Exception as e:
            print(f"❌ 用户认证时发生错误: {e}")
            return False, None

    def create_user(self, data):
        """创建用户 - 增强调试信息"""
        try:
            # 验证必填字段
            if not data.get('username') or not data.get('password') or not data.get('email'):
                return False, "用户名、密码和邮箱为必填项"

            # 检查用户名是否已存在
            existing_user = self.db.get_user_by_username(data['username'])
            if existing_user:
                return False, "用户名已存在"

            # 哈希密码
            hashed_password = self._hash_password(data['password'])
            print(f"🔐 创建用户密码哈希: {data['username']} -> {hashed_password}")

            # 创建用户对象
            user = User(
                id=str(uuid.uuid4()),
                username=data['username'],
                email=data['email'],
                password=hashed_password,
                role=UserRole(data.get('role', 'assistant')),
                created_time=datetime.now()
            )

            # 保存到数据库
            success = self.db.create_user(user)
            if success:
                return True, f"用户 {user.username} 创建成功"
            else:
                return False, "创建用户失败"

        except Exception as e:
            print(f"❌ 创建用户时发生错误: {e}")
            return False, f"创建用户失败: {str(e)}"

    def _hash_password(self, password):
        """密码哈希"""
        return hashlib.sha256(password.encode()).hexdigest()

    def _verify_password(self, password, stored_password):
        """验证密码"""
        # 尝试直接比较（明文）
        if password == stored_password:
            return True
        # 尝试哈希比较
        return self._hash_password(password) == stored_password

class LogService:
    def __init__(self, db):
        self.db = db

    def log_user_action(self, user_id, action, description, ip_address=None):
        """记录用户操作日志"""
        try:
            success = self.db.create_log(user_id, action, description, ip_address)
            if success:
                print(f"📝 日志记录成功: {action} - {description}")
            else:
                print(f"❌ 日志记录失败: {action}")
            return success
        except Exception as e:
            print(f"❌ 记录日志时发生错误: {e}")
            return False

    def get_user_logs(self, user_id, limit=50):
        """获取用户操作日志"""
        try:
            return self.db.get_logs(limit=limit, user_id=user_id)
        except Exception as e:
            print(f"❌ 获取用户日志失败: {e}")
            return []


class SimilarityCheckService:
    def __init__(self):
        pass

    def check_similarity(self, content, existing_questions):
        """检查试题相似度"""
        try:
            similar_questions = []
            content_words = set(content.lower().split())

            for question in existing_questions:
                existing_words = set(question.content.lower().split())

                # 计算Jaccard相似度
                intersection = len(content_words & existing_words)
                union = len(content_words | existing_words)

                if union > 0:
                    similarity = intersection / union
                    if similarity > 0.3:  # 30%以上相似度
                        similar_questions.append({
                            'question': question,
                            'similarity': similarity
                        })

            # 按相似度降序排列
            similar_questions.sort(key=lambda x: x['similarity'], reverse=True)

            return {
                'has_similar': len(similar_questions) > 0,
                'similar_questions': similar_questions[:5],  # 返回前5个
                'max_similarity': similar_questions[0]['similarity'] if similar_questions else 0
            }
        except Exception as e:
            print(f"❌ 相似度检查失败: {e}")
            return {'has_similar': False, 'similar_questions': [], 'max_similarity': 0}


class DifficultyAnalysisService:
    def __init__(self):
        pass

    def analyze_difficulty(self, question):
        """分析试题难度"""
        try:
            # 简单的难度分析逻辑
            content_length = len(question.content)
            word_count = len(question.content.split())

            # 基于内容长度和词汇量估算难度
            if content_length < 50 and word_count < 10:
                predicted = DifficultyLevel.EASY
                confidence = 0.8
            elif content_length < 100 and word_count < 20:
                predicted = DifficultyLevel.MEDIUM
                confidence = 0.7
            elif content_length < 200 and word_count < 40:
                predicted = DifficultyLevel.HARD
                confidence = 0.6
            else:
                predicted = DifficultyLevel.VERY_HARD
                confidence = 0.5

            return {
                'predicted_difficulty': predicted,
                'confidence': confidence,
                'factors': {
                    'content_length': content_length,
                    'word_count': word_count
                }
            }
        except Exception as e:
            print(f"❌ 难度分析失败: {e}")
            return {
                'predicted_difficulty': DifficultyLevel.MEDIUM,
                'confidence': 0.5,
                'factors': {}
            }


class QuestionService:
    def __init__(self, db, similarity_service):
        self.db = db
        self.similarity_service = similarity_service

    def create_question_draft(self, data, creator_id):
        """创建试题草稿"""
        question = Question(
            id=str(uuid.uuid4()),
            content=data['content'],
            question_type=QuestionType(data['question_type']),
            difficulty=DifficultyLevel(data['difficulty']),
            subject=data['subject'],
            chapter=data.get('chapter', ''),
            options=data.get('options', []),
            answer=data.get('answer', ''),
            explanation=data.get('explanation', ''),
            tags=data.get('tags', []),
            usage_count=0,
            creator_id=creator_id,
            created_time=datetime.now()
        )
        return question

    def check_question_similarity(self, question):
        """检查试题相似度"""
        try:
            existing_questions = self.db.search_questions({'subject': question.subject})
            return self.similarity_service.check_similarity(question.content, existing_questions)
        except Exception as e:
            print(f"❌ 相似度检查失败: {e}")
            return {'has_similar': False, 'similar_questions': [], 'max_similarity': 0}

    def finalize_question(self, question):
        """完成试题创建"""
        return self.db.create_question(question)

    def search_questions(self, filters):
        """搜索试题"""
        return self.db.search_questions(filters)


class PaperService:
    def __init__(self, db, difficulty_service):
        self.db = db
        self.difficulty_service = difficulty_service

    def create_manual_paper(self, data, creator_id):
        """手动创建试卷"""
        paper = Paper(
            id=str(uuid.uuid4()),
            title=data['title'],
            description=data.get('description', ''),
            subject=data['subject'],
            questions=data['questions'],
            total_score=sum(q.get('score', 5) for q in data['questions']),
            creator_id=creator_id,
            created_time=datetime.now()
        )
        return paper

    def create_auto_paper(self, data, creator_id):
        """智能组卷"""
        try:
            # 根据条件搜索试题
            filters = {'subject': data['subject']}
            available_questions = self.db.search_questions(filters)

            if not available_questions:
                raise Exception("没有找到符合条件的试题")

            # 按难度分布选择试题
            question_count = data.get('question_count', 10)
            default_score = data.get('default_score', 5)

            easy_count = int(question_count * data.get('difficulty_distribution', {}).get('easy', 30) / 100)
            medium_count = int(question_count * data.get('difficulty_distribution', {}).get('medium', 50) / 100)
            hard_count = question_count - easy_count - medium_count

            selected_questions = []

            # 按难度筛选试题
            easy_questions = [q for q in available_questions if q.difficulty == DifficultyLevel.EASY]
            medium_questions = [q for q in available_questions if q.difficulty == DifficultyLevel.MEDIUM]
            hard_questions = [q for q in available_questions if
                              q.difficulty in [DifficultyLevel.HARD, DifficultyLevel.VERY_HARD]]

            # 选择试题
            selected_questions.extend(
                [{'question_id': q.id, 'score': default_score} for q in easy_questions[:easy_count]])
            selected_questions.extend(
                [{'question_id': q.id, 'score': default_score} for q in medium_questions[:medium_count]])
            selected_questions.extend(
                [{'question_id': q.id, 'score': default_score} for q in hard_questions[:hard_count]])

            paper = Paper(
                id=str(uuid.uuid4()),
                title=data['title'],
                description=f"智能生成的{data['subject']}试卷",
                subject=data['subject'],
                questions=selected_questions,
                total_score=len(selected_questions) * default_score,
                creator_id=creator_id,
                created_time=datetime.now()
            )

            return paper

        except Exception as e:
            print(f"❌ 智能组卷失败: {e}")
            raise e


class EnhancedSimilarityService:
    """增强的相似度检查服务"""

    def __init__(self, db):
        self.db = db
        self.similarity_threshold = 0.8

    def check_question_similarity(self, content: str, existing_questions: List) -> Dict:
        """多算法相似度检查"""
        try:
            similar_results = []

            for question in existing_questions:
                # Jaccard相似度
                jaccard_sim = self._jaccard_similarity(content, question.content)

                # 编辑距离相似度
                edit_sim = self._edit_distance_similarity(content, question.content)

                # TF-IDF余弦相似度
                tfidf_sim = self._tfidf_cosine_similarity(content, question.content)

                # 综合相似度（加权平均）
                combined_sim = (jaccard_sim * 0.3 + edit_sim * 0.3 + tfidf_sim * 0.4)

                if combined_sim >= self.similarity_threshold:
                    similar_results.append({
                        'question': question,
                        'similarity': combined_sim,
                        'jaccard_similarity': jaccard_sim,
                        'edit_similarity': edit_sim,
                        'tfidf_similarity': tfidf_sim
                    })

            # 按相似度降序排列
            similar_results.sort(key=lambda x: x['similarity'], reverse=True)

            return {
                'has_similar': len(similar_results) > 0,
                'similar_questions': similar_results[:5],
                'max_similarity': similar_results[0]['similarity'] if similar_results else 0,
                'total_checked': len(existing_questions)
            }
        except Exception as e:
            print(f"❌相似度检查失败: {e}")
            return {'has_similar': False, 'similar_questions': [], 'max_similarity': 0}

    def _jaccard_similarity(self, text1: str, text2: str) -> float:
        """Jaccard相似度计算"""
        try:
            set1 = set(jieba.cut(text1.lower()))
            set2 = set(jieba.cut(text2.lower()))
            intersection = len(set1 & set2)
            union = len(set1 | set2)
            return intersection / union if union > 0 else 0
        except:
            # 如果jieba分词失败，使用简单的空格分词
            set1 = set(text1.lower().split())
            set2 = set(text2.lower().split())
            intersection = len(set1 & set2)
            union = len(set1 | set2)
            return intersection / union if union > 0 else 0

    def _edit_distance_similarity(self, text1: str, text2: str) -> float:
        """编辑距离相似度"""

        def edit_distance(s1, s2):
            m, n = len(s1), len(s2)
            dp = [[0] * (n + 1) for _ in range(m + 1)]

            for i in range(m + 1):
                dp[i][0] = i
            for j in range(n + 1):
                dp[0][j] = j

            for i in range(1, m + 1):
                for j in range(1, n + 1):
                    if s1[i - 1] == s2[j - 1]:
                        dp[i][j] = dp[i - 1][j - 1]
                    else:
                        dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1

            return dp[m][n]

        max_len = max(len(text1), len(text2))
        if max_len == 0:
            return 1.0
        distance = edit_distance(text1, text2)
        return 1 - (distance / max_len)

    def _tfidf_cosine_similarity(self, text1: str, text2: str) -> float:
        """TF-IDF余弦相似度"""
        try:
            vectorizer = TfidfVectorizer()
            tfidf_matrix = vectorizer.fit_transform([text1, text2])
            similarity = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])[0][0]
            return float(similarity)
        except:
            return 0.0


class EnhancedDifficultyAnalysisService:
    """增强的难度分析服务"""

    def __init__(self, db):
        self.db = db

    def analyze_question_difficulty(self, question) -> Dict:
        """深度分析试题难度"""
        try:
            factors = {}

            # 文本长度因子
            content_length = len(question.content)
            factors['content_length'] = content_length
            factors['content_length_score'] = min(content_length / 200, 1.0)

            # 词汇复杂度
            try:
                words = list(jieba.cut(question.content))
            except:
                words = question.content.split()

            word_count = len(words)
            unique_words = len(set(words))
            factors['word_count'] = word_count
            factors['vocabulary_diversity'] = unique_words / word_count if word_count > 0 else 0

            # 专业术语密度
            professional_terms = self._count_professional_terms(question.content, question.subject)
            factors['professional_terms_count'] = professional_terms
            factors['professional_density'] = professional_terms / word_count if word_count > 0 else 0

            # 综合难度预测
            predicted_difficulty = self._calculate_predicted_difficulty(factors)
            confidence = self._calculate_confidence(factors)

            # 保存分析结果
            self.db.save_difficulty_analysis(
                question.id,
                predicted_difficulty,
                question.difficulty.value,
                confidence,
                factors
            )

            return {
                'predicted_difficulty': predicted_difficulty,
                'confidence': confidence,
                'analysis_factors': factors
            }
        except Exception as e:
            print(f"❌难度分析失败: {e}")
            return {
                'predicted_difficulty': 2,
                'confidence': 0.5,
                'analysis_factors': {}
            }

    def _count_professional_terms(self, content: str, subject: str) -> int:
        """计算专业术语数量"""
        professional_terms = {
            '数学': ['函数', '方程', '积分', '微分', '矩阵', '向量'],
            '物理': ['力学', '电磁', '光学', '热力学', '量子'],
            '化学': ['分子', '原子', '离子', '反应', '催化']
        }

        terms = professional_terms.get(subject, [])
        count = 0
        for term in terms:
            count += content.count(term)
        return count

    def _calculate_predicted_difficulty(self, factors: Dict) -> int:
        """根据因子计算预测难度"""
        score = 0
        score += factors.get('content_length_score', 0) * 0.4
        score += factors.get('vocabulary_diversity', 0) * 0.3
        score += factors.get('professional_density', 0) * 0.3

        if score <= 0.3:
            return 1  # 简单
        elif score <= 0.6:
            return 2  # 中等
        elif score <= 0.8:
            return 3  # 困难
        else:
            return 4  # 非常困难

    def _calculate_confidence(self, factors: Dict) -> float:
        """计算预测置信度"""
        factor_count = len([v for v in factors.values() if v > 0])
        base_confidence = min(factor_count / 5, 1.0)
        return max(0.4, base_confidence)